package logica.persistencia;


import java.util.List;
import logica.Diagrama;
import logica.Entidad;
import logica.EntidadRepetidaException;
import logica.EntidadRol;
import logica.IdExternoInexistenteException;
import logica.Jerarquia;
import logica.JerarquiaException;
import logica.ObjetoDiagrama;
import logica.Relacion;
import logica.RelacionException;
import logica.SinNombreException;

import org.jdom.Element;

import xml.ConstantesXml;
import xml.XMLManager;


public abstract  class DiagramaPersistente {
	private Diagrama diagrama;
	
	int identificador = 0;
	private Element elementoDiagrama;
		
	public DiagramaPersistente(Diagrama diagrama) {
		this.setDiagrama(diagrama);
		identificador= XMLManager.getIdentificador(diagrama);
	}
	
	public DiagramaPersistente() {
		
	}

	public Diagrama getDiagrama() {
		return diagrama;
	}

	public void setDiagrama(Diagrama diagrama) {
		this.diagrama = diagrama;
	}
	
	public Element getElementoDiagrama() {
		return elementoDiagrama;
	}

	public void setElementoDiagrama(Element elementoDiagrama) {
		this.elementoDiagrama = elementoDiagrama;
	}
	


	public void serializarDiagramaGenerico() {
		
		
		Element elementoDiagrama = new Element(ConstantesXml.ELEMENTO_DIAGRAMA);
		XMLManager.getInstance().agregarRaiz(elementoDiagrama);
		
		this.setElementoDiagrama(elementoDiagrama);
		String idDiagrama= String.valueOf(identificador);
		
		elementoDiagrama.setAttribute(ConstantesXml.ATRIBUTO_NOMBRE, diagrama.getNombre());
		elementoDiagrama.setAttribute(ConstantesXml.ATRIBUTO_ID_OBJETO, idDiagrama);
		
		Element objetos = new Element (ConstantesXml.ELEMENTO_OBJETOS);
		elementoDiagrama.addContent(objetos);
		
		XMLManager.getInstance().hashObjetoDiagramaConClave(idDiagrama, this.diagrama);

		
		List<Entidad> entidades = diagrama.getEntidades();
		
		for (Entidad ent : entidades) {
			
			EntidadPersistente entP = ent.getObjetoDiagramaPersistente();
			entP.serializar();
		}
		
		List<ObjetoDiagrama> objetosDiagrama = diagrama.getObjetosDiagramas();
		for (ObjetoDiagrama obj : objetosDiagrama) {
			ObjetoDiagramaPersistente objPers = obj.getObjetoDiagramaPersistente();
			objPers.serializar();
			
		}
		
		List<Diagrama> diagramasHijos = this.getDiagrama().getDiagramasHijo();		
		

		if (elementoDiagrama != null) {
			Element listaDiagramasHijos = new Element(ConstantesXml.LISTA_DIAGRAMAS_HIJOS);
			for (Diagrama diagrama : diagramasHijos ) {
				int ref = XMLManager.getIdentificador(diagrama);
				Element diagramaHijo = new Element(ConstantesXml.ELEMENTO_DIAGRAMA_HIJO);
				diagramaHijo.setAttribute(ConstantesXml.ATRIBUTO_ID_REF, String.valueOf(ref));;
				diagramaHijo.setAttribute(ConstantesXml.ATRIBUTO_NOMBRE_REF, diagrama.getNombre());;
				listaDiagramasHijos.addContent(diagramaHijo);
			}
			elementoDiagrama.addContent(listaDiagramasHijos);
		} 
		
	}
	
	private void hidratarEntidades(Element objetos) {
		@SuppressWarnings("unchecked")
		List<Element> elementosEntidades = objetos.getChildren(ConstantesXml.ELEMENTO_ENTIDAD);
		
		for (Element elementoEntidad : elementosEntidades) {
			String nombreEntidad = elementoEntidad.getAttributeValue(ConstantesXml.ATRIBUTO_NOMBRE);
			
			String idRef = elementoEntidad.getAttributeValue(ConstantesXml.ATRIBUTO_ID_OBJETO);
			
			
			try {
				Boolean entidadYaAgregada = verificarEntidadEnDiagramaPrincipal(nombreEntidad);
				if (!entidadYaAgregada) {
					Entidad entidad = new Entidad(nombreEntidad);
					XMLManager.getInstance().hashObjetoDiagramaConClave(idRef, entidad);
					EntidadPersistente entidadPersistente = new EntidadPersistente(entidad);
					entidadPersistente.hidratar(elementoEntidad);
					this.diagrama.agregarObjetoDiagrama(entidad);
				}
			} 
			catch (IdExternoInexistenteException e) {
					e.printStackTrace();
			} catch (EntidadRepetidaException e) {
				e.printStackTrace();
			} catch (SinNombreException e) {
				e.printStackTrace();
			}
			
		}
	}
	
	private void hidratarIdentificadores(Element objetos) {
		@SuppressWarnings("unchecked")
		List<Element> elementosEntidades = objetos.getChildren(ConstantesXml.ELEMENTO_ENTIDAD);
		
		for (Element elementoEntidad : elementosEntidades) {
						
			String idRef = elementoEntidad.getAttributeValue(ConstantesXml.ATRIBUTO_ID_OBJETO);
			Entidad entidad = (Entidad)XMLManager.getInstance().objtenerObjetoDiagramaConClave(idRef);
			if (entidad!=null) {
				
				EntidadPersistente entidadPersistente = entidad.getObjetoDiagramaPersistente();
				entidadPersistente.hidratarIdentificadores(elementoEntidad);
			}
		}
	}
		
	public abstract Boolean verificarEntidadEnDiagramaPrincipal(String nombreEntidad);
		

	private void hidratarRelaciones(Element objetos) {
		@SuppressWarnings("unchecked")
		List<Element> elementosRelaciones = objetos.getChildren(ConstantesXml.ELEMENTO_RELACION);
		
		for (Element elementoRelacion : elementosRelaciones) {
			String nombreRelacion = elementoRelacion.getAttributeValue(ConstantesXml.ATRIBUTO_NOMBRE);
			List<EntidadRol> entidadesRol = EntidadRolPersistente.hidratarEntidadesRol(elementoRelacion);
			try {
				Relacion relacion = new Relacion(nombreRelacion, entidadesRol);
				RelacionPersistente relacionPersistente = new RelacionPersistente(relacion);
				relacionPersistente.hidratar(elementoRelacion);
				this.diagrama.agregarObjetoDiagrama(relacion);
			} 
			catch (IdExternoInexistenteException e) {
					e.printStackTrace();
			} catch (EntidadRepetidaException e) {
				e.printStackTrace();
			} catch (SinNombreException e) {
				e.printStackTrace();
			} catch (RelacionException e) {
				e.printStackTrace();
			}
			
		}
		
	}
	
	private void hidratarJerarquias(Element objetos) {
		@SuppressWarnings("unchecked")
		List<Element> elementosJerarquias = objetos.getChildren(ConstantesXml.ELEMENTO_JERARQUIA);
		for (Element elementoJerarquia : elementosJerarquias) {
			String nombreJerarquia = elementoJerarquia.getAttributeValue(ConstantesXml.ATRIBUTO_NOMBRE);
			List<Entidad> entidadesEspecializadas = JerarquiaPersistente.hidratarEntidadesEspecializadas(elementoJerarquia);
			Entidad entidadPadre = EntidadPersistente.hidratarEntidadEnHash(elementoJerarquia);
			
			try {
				Jerarquia jerarquia = new Jerarquia(nombreJerarquia, entidadPadre, entidadesEspecializadas);
				JerarquiaPersistente jerarquiaPersistente = new JerarquiaPersistente(jerarquia);
				jerarquiaPersistente.hidratar(elementoJerarquia);
				this.diagrama.agregarObjetoDiagrama(jerarquia);
			} 
			catch (IdExternoInexistenteException e) {
					e.printStackTrace();
			} catch (EntidadRepetidaException e) {
				e.printStackTrace();
			} catch (SinNombreException e) {
				e.printStackTrace();
			} catch (JerarquiaException e) {
				e.printStackTrace();
			}
			
		}
	}
	
	public void hidratarDiagramaGenerico() {
		
		Element elementoDiagrama = XMLManager.getInstance().obtenerRaiz();
		this.setElementoDiagrama(elementoDiagrama);
		String nombreDiagrama = elementoDiagrama.getAttributeValue(ConstantesXml.ATRIBUTO_NOMBRE);

		String idRef = elementoDiagrama.getAttributeValue(ConstantesXml.ATRIBUTO_ID_OBJETO);
		XMLManager.getInstance().hashObjetoDiagramaConClave(idRef, this.diagrama);
		
		try {
			this.diagrama.setNombre(nombreDiagrama);
			Element objetos = elementoDiagrama.getChild(ConstantesXml.ELEMENTO_OBJETOS);
			
			if (objetos != null) {
				this.hidratarEntidades(objetos);
				this.hidratarRelaciones(objetos);
				this.hidratarJerarquias(objetos);
				this.hidratarIdentificadores(objetos);
				this.hidratarDiagramasHijos();
				
			}
			
		} catch (SinNombreException e) {
			e.printStackTrace();
		}
	}

	private void hidratarDiagramasHijos() {
		Element elementoDiagramasHijos = elementoDiagrama.getChild(ConstantesXml.LISTA_DIAGRAMAS_HIJOS);
		if (elementoDiagramasHijos != null ) {
			@SuppressWarnings("unchecked")
			List <Element> listaElementoDiagramasHijos = elementoDiagramasHijos.getChildren(ConstantesXml.ELEMENTO_DIAGRAMA_HIJO);
			for (Element elementoDiagramaHijo : listaElementoDiagramasHijos) {
				String nombreDiag = elementoDiagramaHijo.getAttributeValue(ConstantesXml.ATRIBUTO_NOMBRE_REF);
				try {
					this.diagrama.crearDiagramaHijo(nombreDiag);
				} catch (SinNombreException e) {
					e.printStackTrace();
				}				
			}
		}
		
	}

	
	

}
